﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Drawing.Drawing2D;

namespace CustomControls
{
    public partial class DoubleSlider : UserControl
    {
        public event EventHandler ValueChanged;

        private enum SelectedMarker { Left, Right, Both, None }
        private SelectedMarker marker = SelectedMarker.None;
        private Point[] polygonRightPoints = new Point[3];
        private Point[] polygonLeftPoints = new Point[3];
        private Point mouseStartPosition;
        private Rectangle sliderRectangle;

        private StringFormat rightAlignedFormat;
        private StringFormat leftAlignedFormat;


        private int maxValue;
        public int MaxValue
        {
            get { return maxValue; }
            set { maxValue = value; }
        }

        public Brush ColorBrush
        {
            get;
            set;
        }
        public Brush DisabledColorBrush
        {
            get;
            set;
        }

        private int lowerValue;
        public int LowerValue
        {
            get
            {
                return lowerValue;
            }

            set
            {
                lowerValue = value;
                if ((UpperValue <= value) && (upperValue != 0))
                {
                    //lowerValue = UpperValue;
                    UpperValue = lowerValue;
                }
                else
                {
                    //lowerValue = value;
                }
                try
                {
                    ValueChanged(this, new EventArgs());
                }
                catch { }
            }
        }

        private int upperValue;
        public int UpperValue
        {
            get { return upperValue; }
            set
            {

                if (value > maxValue)
                {
                    upperValue = maxValue;
                }
                else
                {
                    upperValue = value;
                }
                if (LowerValue > value)
                {
                    //upperValue = LowerValue;
                    LowerValue = upperValue;
                }
                else
                {
                    //upperValue = value;
                }
                try
                {
                    ValueChanged(this, new EventArgs());
                }
                catch { }
            }
        }
        public DoubleSlider()
        {
            InitializeComponent();
            DoubleBuffered = true;
            SetStyle(ControlStyles.DoubleBuffer, true);
            SetStyle(ControlStyles.UserPaint, true);
            SetStyle(ControlStyles.AllPaintingInWmPaint, true);
            ColorBrush = new LinearGradientBrush(new Point(0, 0), new Point(0, sliderPanel.Height), Color.LightBlue, Color.Blue);
            DisabledColorBrush = new LinearGradientBrush(new Point(0, 0), new Point(0, sliderPanel.Height), Color.LightGray, Color.Gray);
            rightAlignedFormat = new StringFormat();
            rightAlignedFormat.Alignment = StringAlignment.Far;
            rightAlignedFormat.LineAlignment = StringAlignment.Near;

            leftAlignedFormat = new StringFormat();
            leftAlignedFormat.Alignment = StringAlignment.Near;
            leftAlignedFormat.LineAlignment = StringAlignment.Near;
        }



        private void sliderPanel_Paint(object sender, PaintEventArgs e)
        {
            if (this.DesignMode) return;

            e.Graphics.FillRectangle(this.Enabled ? ColorBrush : DisabledColorBrush,
                sliderRectangle);
            SizeF measureStringLeft = e.Graphics.MeasureString(LowerValue.ToString(), new Font("Arial", 8));
            SizeF measureStringRight = e.Graphics.MeasureString(UpperValue.ToString(), new Font("Arial", 8));
            double lowerValueToWidth = (double)LowerValue / (double)maxValue * (double)markerPanel.Width;
            double upperValueToWidth = (double)UpperValue / (double)maxValue * (double)markerPanel.Width;
            e.Graphics.DrawString(LowerValue.ToString(), new Font("Arial", 8), Brushes.Black, new Point((int)lowerValueToWidth, 0), lowerValueToWidth < markerPanel.Width - measureStringLeft.Width ? leftAlignedFormat : rightAlignedFormat); //Left aligned oder right aligned, damit zahlen nicht aus dem bild laufen
            e.Graphics.DrawString(UpperValue.ToString(), new Font("Arial", 8), Brushes.Black, new Point((int)upperValueToWidth, (lowerValueToWidth + measureStringLeft.Width > upperValueToWidth - measureStringRight.Width) ? 9 : 0), upperValueToWidth >= measureStringRight.Width ? rightAlignedFormat : leftAlignedFormat); //alignment wie oben, außerdem string um 9 nach unten verschieben, falls zahlen sich überlappen
        }

        private void markerPanel_Paint(object sender, PaintEventArgs e)
        {
            if (this.DesignMode) return;

            double upperValueToWidth = (double)UpperValue / (double)maxValue * (double)markerPanel.Width;
            polygonRightPoints[0] = new Point((int)upperValueToWidth, 0);
            polygonRightPoints[1] = new Point((int)upperValueToWidth + 5, markerPanel.Height);
            polygonRightPoints[2] = new Point((int)upperValueToWidth - 5, markerPanel.Height);


            double lowerValueToWidth = (double)LowerValue / (double)maxValue * (double)markerPanel.Width;
            polygonLeftPoints[0] = new Point((int)lowerValueToWidth, 0);
            polygonLeftPoints[1] = new Point((int)lowerValueToWidth + 5, markerPanel.Height);
            polygonLeftPoints[2] = new Point((int)lowerValueToWidth - 5, markerPanel.Height);
            sliderRectangle = new Rectangle((int)lowerValueToWidth, 0, (int)(upperValueToWidth - lowerValueToWidth), sliderPanel.Height);
            e.Graphics.FillPolygon(Brushes.Gray, polygonLeftPoints);
            e.Graphics.FillPolygon(Brushes.Gray, polygonRightPoints);

        }



        private void markerPanel_MouseDown(object sender, MouseEventArgs e)
        {

            mouseStartPosition = e.Location;


            if (HitTest(polygonRightPoints, mouseStartPosition))
            {
                if (e.Button == System.Windows.Forms.MouseButtons.Right || e.Clicks == 2)
                {
                    NumberForm nForm = new NumberForm();
                    nForm.StartPosition = FormStartPosition.Manual;
                    nForm.Location = Cursor.Position;
                    nForm.MinValue = LowerValue;
                    nForm.MaxValue = MaxValue;
                    nForm.Value = UpperValue;
                    if (nForm.ShowDialog() == DialogResult.OK)
                    {
                        UpperValue = nForm.Value;
                        this.Invalidate();
                    }
                    nForm.Dispose();
                }
                else
                {
                    marker = SelectedMarker.Right;
                }
            }
            else if (HitTest(polygonLeftPoints, mouseStartPosition))
            {
                if (e.Button == System.Windows.Forms.MouseButtons.Right || e.Clicks == 2)
                {
                    NumberForm nForm = new NumberForm();
                    nForm.StartPosition = FormStartPosition.Manual;
                    nForm.Location = Cursor.Position;
                    nForm.MinValue = 0;
                    nForm.MaxValue = UpperValue;
                    nForm.Value = LowerValue;
                    if (nForm.ShowDialog() == DialogResult.OK)
                    {
                        LowerValue = nForm.Value;
                        this.Invalidate();
                    }
                    nForm.Dispose();
                }
                else
                {
                    marker = SelectedMarker.Left;
                }
            }
            else
            {
                marker = SelectedMarker.None;
            }
        }

        private void markerPanel_MouseMove(object sender, MouseEventArgs e)
        {
            Point currMousePosition = e.Location;
            if (currMousePosition.X < 0)
            {
                currMousePosition.X = 0;
            }
            if (currMousePosition.X > markerPanel.Width)
            {
                currMousePosition.X = markerPanel.Width;
            }


            switch (marker)
            {
                case SelectedMarker.Left:
                    LowerValue = (int)((double)Math.Abs(currMousePosition.X) / (double)markerPanel.Width * (double)maxValue);
                    this.Invalidate(true);
                    break;
                case SelectedMarker.Right:
                    UpperValue = (int)((double)Math.Abs(currMousePosition.X) / (double)markerPanel.Width * (double)maxValue);
                    this.Invalidate(true);
                    break;
            }
        }

        private bool HitTest(Point[] triangle, Point testPoint)
        {
            //Test er folgt mit umschließendem Rechteck

            if (testPoint.Y >= triangle[0].Y && testPoint.Y <= triangle[1].Y && //Höhe testen
            testPoint.X >= triangle[2].X && testPoint.X <= triangle[1].X)
            {
                return true;
            }
            else
            {
                return false;
            }

        }

        private void markerPanel_MouseUp(object sender, MouseEventArgs e)
        {
            marker = SelectedMarker.None;
        }

        private void sliderPanel_MouseDown(object sender, MouseEventArgs e)
        {
            if (sliderRectangle.Contains(e.Location))
            {
                marker = SelectedMarker.Both;
            }
            mouseStartPosition = e.Location;
        }

        private void sliderPanel_MouseMove(object sender, MouseEventArgs e)
        {
            if (marker == SelectedMarker.Both)
            {
                Point currMousePosition = e.Location;
                if (LowerValue < 0)
                {
                    LowerValue = 0;
                }
                if (UpperValue > maxValue)
                {
                    UpperValue = maxValue;
                }


                if (LowerValue > 0)
                {
                    UpperValue += (int)(((double)currMousePosition.X - (double)mouseStartPosition.X) / (double)markerPanel.Width * (double)maxValue);
                }
                if (UpperValue < maxValue)
                {
                    LowerValue += (int)(((double)currMousePosition.X - (double)mouseStartPosition.X) / (double)markerPanel.Width * (double)maxValue);
                }
                this.Invalidate(true);

                mouseStartPosition = currMousePosition;
                if (LowerValue < 0)
                {
                    LowerValue = 0;
                }
                if (UpperValue > maxValue)
                {
                    UpperValue = maxValue;
                }
            }
        }

        private void sliderPanel_MouseUp(object sender, MouseEventArgs e)
        {
            marker = SelectedMarker.None;
        }




    }
}
